﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using GCTrackableRace.Interfaces;
using GcTrackableRace.Entities;

namespace GcTrackableRace.ScoreCalculator.Rules
{
	public class NotMovedRule : BaseRule, IRaceRule
	{
		public NotMovedRule(string reportColumnName, string startDate, string endDate, string pointAllocation, IGeocacheInfo geocacheInfo)
			: base(reportColumnName, startDate, endDate, pointAllocation)
		{
			GeocacheInfo = geocacheInfo;
		}

		private IGeocacheInfo GeocacheInfo { get; set; }

		protected override void SetRuleName()
		{
			RuleName = "Not moved rule";
		}

		public override void Process(ITrackable trackable, IEnumerable<ITrackableLog> trackableLogs)
		{
			var allDroppedAndVisitedLogs = (
				from log in trackableLogs
				where (
					(log.LogType == LogType.DroppedOff || log.LogType == LogType.Visited)
					&&
						(
							log.Date >= StartDate
							&&
							log.Date <= EndDate
						)
					)
				select log)
				.OrderBy(logs => logs.Date)
				.ThenBy(logs => logs.LogId)
				.ToList();

			var tbNotMovedCache = new List<string>();

			if (!allDroppedAndVisitedLogs.Any())
			{
				var result = GetLastCacheTrackableWasIn(trackableLogs);

				if (result != null)
				{
					tbNotMovedCache.Add(result);
				}
			}

			trackable.AddScore(new RuleScore(
				RuleName, 
				ReportColumnName,
				tbNotMovedCache.Count,
				(int)(tbNotMovedCache.Count * PointAllocation),
				String.Join("|", tbNotMovedCache).Trim('|')));
		}

		private string GetLastCacheTrackableWasIn(IEnumerable<ITrackableLog> trackableLogs)
		{
			var lastPreviousLog = (
				from log in trackableLogs
				where (
				  log.Date < StartDate
				  &&
				  (log.LogType == LogType.DroppedOff || log.LogType == LogType.Visited))
				select log
			)
			.ToList()
			.OrderByDescending(l => l.Date)
			.ThenByDescending(l => l.LogId)
			.FirstOrDefault();

			if (lastPreviousLog != null && lastPreviousLog.LogType == "Dropped Off")
			{
				return lastPreviousLog.LocationGcCode;
			}

			return null;
		}
	}
}
